//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<DxHelpers.cpp>
///	@path	~/src/graphics/
///	@date	2007/12/16
///	@desc	Some helper function for DirectX.

#include "config/config.h"

#include <map>
#include <dxerr.h>
#include <d3d10.h>
#include "graphics/DxHelpers.h"
#include "graphics/IGeometry.h"

namespace xeres {

	const char * dxgi_to_hlsl_type( DXGI_FORMAT format )
	{
		static std::map<DXGI_FORMAT,const char*> s_format;
		if( s_format.empty() )
		{
			s_format[DXGI_FORMAT_R32G32B32A32_FLOAT]	= "float4";
			s_format[DXGI_FORMAT_R32G32B32A32_UINT]		= "uint4";
			s_format[DXGI_FORMAT_R32G32B32A32_SINT]		= "int4";
			s_format[DXGI_FORMAT_R32G32B32_FLOAT]		= "float3";
			s_format[DXGI_FORMAT_R32G32B32_UINT] 		= "uint3";
			s_format[DXGI_FORMAT_R32G32B32_SINT] 		= "int3";
			s_format[DXGI_FORMAT_R16G16B16A16_FLOAT]	= "half4";
			s_format[DXGI_FORMAT_R16G16B16A16_UNORM]	= "unorm half4";
			s_format[DXGI_FORMAT_R16G16B16A16_UINT]		= "half4";
			s_format[DXGI_FORMAT_R16G16B16A16_SNORM]	= "snorm half4";
			s_format[DXGI_FORMAT_R16G16B16A16_SINT]		= "half4";
			s_format[DXGI_FORMAT_R32G32_FLOAT]			= "float2";
			s_format[DXGI_FORMAT_R32G32_UINT]			= "uint2";
			s_format[DXGI_FORMAT_R32G32_SINT]			= "int2";

			s_format[DXGI_FORMAT_R8G8B8A8_UNORM]		= "float4";
			s_format[DXGI_FORMAT_R8G8B8A8_UNORM_SRGB]	= "float4";
			s_format[DXGI_FORMAT_R8G8B8A8_UINT]			= "int4";
			s_format[DXGI_FORMAT_R8G8B8A8_SNORM]		= "snorm float4";
			s_format[DXGI_FORMAT_R8G8B8A8_SINT]			= "int4";
			s_format[DXGI_FORMAT_R16G16_FLOAT]			= "half2";
			s_format[DXGI_FORMAT_R16G16_UNORM]			= "unorm half2";
			s_format[DXGI_FORMAT_R16G16_UINT]			= "half2";
			s_format[DXGI_FORMAT_R16G16_SNORM]			= "snorm half2";
			s_format[DXGI_FORMAT_R16G16_SINT]			= "half2";
			s_format[DXGI_FORMAT_D32_FLOAT]				= "float";
			s_format[DXGI_FORMAT_R32_FLOAT]				= "float";
			s_format[DXGI_FORMAT_R32_UINT]				= "uint";
			s_format[DXGI_FORMAT_R32_SINT]				= "int";
			s_format[DXGI_FORMAT_R8G8_UNORM]			= "unorm half2";
			s_format[DXGI_FORMAT_R8G8_UINT]				= "uint2";
			s_format[DXGI_FORMAT_R8G8_SNORM]			= "snorm half2";
			s_format[DXGI_FORMAT_R8G8_SINT]				= "int2";
			s_format[DXGI_FORMAT_R16_FLOAT]				= "half";
			s_format[DXGI_FORMAT_D16_UNORM]				= "unorm half";
			s_format[DXGI_FORMAT_R16_UNORM]				= "unorm half";
			s_format[DXGI_FORMAT_R16_UINT]				= "half";
			s_format[DXGI_FORMAT_R16_SNORM]				= "snorm half";
			s_format[DXGI_FORMAT_R16_SINT]				= "half";
			s_format[DXGI_FORMAT_R8_UNORM]				= "unorm float";
			s_format[DXGI_FORMAT_R8_UINT]				= "float";
			s_format[DXGI_FORMAT_R8_SNORM]				= "snorm float";
			s_format[DXGI_FORMAT_R8_SINT]				= "float";
			s_format[DXGI_FORMAT_A8_UNORM]				= "unorm float";

			s_format[DXGI_FORMAT_B8G8R8A8_UNORM]		= "unorm float4";
			s_format[DXGI_FORMAT_B8G8R8X8_UNORM]		= "unorm float4";
			s_format[DXGI_FORMAT_B8G8R8A8_UNORM_SRGB]	= "unorm float4";
			s_format[DXGI_FORMAT_B8G8R8X8_UNORM_SRGB]	= "unorm float4";
		}
		return s_format.find( format )->second;
	}

	// d3d_vertex_to_hlsl_type
	const char * d3d_vertex_to_hlsl_type( D3DDECLTYPE type )
	{
		static std::map<D3DDECLTYPE,const char*> s_format;
		if( s_format.empty() )
		{
			s_format[D3DDECLTYPE_FLOAT1]		=	"float";
			s_format[D3DDECLTYPE_FLOAT2]		=	"float2";
			s_format[D3DDECLTYPE_FLOAT3]		=	"float3";
			s_format[D3DDECLTYPE_FLOAT4]		=	"float4";
			s_format[D3DDECLTYPE_D3DCOLOR]		=	"float4";

			s_format[D3DDECLTYPE_UBYTE4]		=	"float4";
			s_format[D3DDECLTYPE_SHORT2]		=	"float2";
			s_format[D3DDECLTYPE_SHORT4]		=	"float4";

			s_format[D3DDECLTYPE_UBYTE4N]		=	"float4";
			s_format[D3DDECLTYPE_SHORT2N]		=	"float2";
			s_format[D3DDECLTYPE_SHORT4N]		=	"float4";
			s_format[D3DDECLTYPE_USHORT2N]		=	"float2";
			s_format[D3DDECLTYPE_USHORT4N]		=	"float2";
			s_format[D3DDECLTYPE_UDEC3]			=	"float3";
			s_format[D3DDECLTYPE_DEC3N]			=	"float3";
			s_format[D3DDECLTYPE_FLOAT16_2]		=	"half2";
			s_format[D3DDECLTYPE_FLOAT16_4]		=	"half4";;
		}
		return s_format.find( type )->second;
	}

	// d3d_usage_to_semantic
	const char * d3d_usage_to_semantic( D3DDECLUSAGE usage , int index )
	{
		switch( usage )
		{
		case D3DDECLUSAGE_POSITION:
			return "POSITION";
		case D3DDECLUSAGE_BLENDWEIGHT:
			return "BLENDWEIGHT";
		case D3DDECLUSAGE_BLENDINDICES:
			return "BLENDINDICES";
		case D3DDECLUSAGE_NORMAL:
			return "NORMAL";
		case D3DDECLUSAGE_PSIZE:
			return "PSIZE";
		case D3DDECLUSAGE_TEXCOORD:
			switch(index)
			{
			case 0: return "TEXCOORD";
			case 1: return "TEXCOORD1";
			case 2: return "TEXCOORD2";
			case 3: return "TEXCOORD3";
			case 4: return "TEXCOORD4";
			case 5: return "TEXCOORD5";
			case 6: return "TEXCOORD6";
			case 7: return "TEXCOORD7";
			default:
				XS_ASSERT(false);
				return NULL;
			}
		case D3DDECLUSAGE_TANGENT:
			return "TANGENT";
		case D3DDECLUSAGE_BINORMAL:
			return "BINORMAL";
		case D3DDECLUSAGE_TESSFACTOR:
			return "TESSFACTOR";
		case D3DDECLUSAGE_POSITIONT:
			return "POSITIONT";
		case D3DDECLUSAGE_COLOR:
			switch(index)
			{
			case 0: return "COLOR";
			case 1: return "COLOR1";
			default:
				XS_ASSERT(false);
				return NULL;
			}
		case D3DDECLUSAGE_FOG:
			return "FOG";
		case D3DDECLUSAGE_DEPTH:
			return "DEPTH";
		case D3DDECLUSAGE_SAMPLE:
			return "SAMPLE";
		}
		return NULL;
	}

	// d3d_devtype_to_string
	const WString& d3d_devtype_to_string( D3DDEVTYPE type )
	{
		switch( type )
		{
		case D3DDEVTYPE_HAL: { static const WString s_hal( _S("HAL") ); return s_hal; } break;
		case D3DDEVTYPE_REF: { static const WString s_ref( _S("REF") ); return s_ref; } break;
		case D3DDEVTYPE_SW: { static const WString s_sw( _S("SW") ); return s_sw; } break;

		default:
			{
				 static const WString s_default( _S("Unknown device type") );
				 return s_default;
			}
		}
	}

	// d3d10_drvtype_to_string
	const WString& d3d10_drvtype_to_string( D3D10_DRIVER_TYPE type )
	{
		switch( type )
		{
		case D3D10_DRIVER_TYPE_HARDWARE: { static const WString s_hal( _S("HARDWARE") ); return s_hal; } break;
		case D3D10_DRIVER_TYPE_REFERENCE: { static const WString s_ref( _S("REFERENCE") ); return s_ref; } break;
		case D3D10_DRIVER_TYPE_SOFTWARE: { static const WString s_sw( _S("SOFTWARE") ); return s_sw; } break;

		default:
			{
				 static const WString s_default( _S("Unknown device type") );
				 return s_default;
			}
		}
	}

	// d3d_format_to_string
	const WString& d3d_format_to_string( D3DFORMAT format )
	{
		switch( format )
		{

#define	FMT_2_STRING( FMT )		case D3DFMT_##FMT##: { static const WString s_##FMT##( L#FMT ); return s_##FMT##; } break

		FMT_2_STRING(UNKNOWN);
		FMT_2_STRING(R8G8B8);
		FMT_2_STRING(A8R8G8B8);
		FMT_2_STRING(X8R8G8B8);
		FMT_2_STRING(R5G6B5);
		FMT_2_STRING(X1R5G5B5);
		FMT_2_STRING(A1R5G5B5);
		FMT_2_STRING(A4R4G4B4);
		FMT_2_STRING(R3G3B2);
		FMT_2_STRING(A8);
		FMT_2_STRING(A8R3G3B2);
		FMT_2_STRING(X4R4G4B4);
		FMT_2_STRING(A2B10G10R10);
		FMT_2_STRING(A8B8G8R8);
		FMT_2_STRING(X8B8G8R8);
		FMT_2_STRING(G16R16);
		FMT_2_STRING(A2R10G10B10);
		FMT_2_STRING(A16B16G16R16);
		FMT_2_STRING(A8P8);
		FMT_2_STRING(P8);
		FMT_2_STRING(L8);
		FMT_2_STRING(A8L8);
		FMT_2_STRING(A4L4);
		FMT_2_STRING(V8U8);
		FMT_2_STRING(L6V5U5);
		FMT_2_STRING(X8L8V8U8);
		FMT_2_STRING(Q8W8V8U8);
		FMT_2_STRING(V16U16);
		FMT_2_STRING(A2W10V10U10);
		FMT_2_STRING(UYVY);
		FMT_2_STRING(YUY2);
		FMT_2_STRING(DXT1);
		FMT_2_STRING(DXT2);
		FMT_2_STRING(DXT3);
		FMT_2_STRING(DXT4);
		FMT_2_STRING(DXT5);
		FMT_2_STRING(D16_LOCKABLE);
		FMT_2_STRING(D32);
		FMT_2_STRING(D15S1);
		FMT_2_STRING(D24S8);
		FMT_2_STRING(D24X8);
		FMT_2_STRING(D24X4S4);
		FMT_2_STRING(D16);
		FMT_2_STRING(L16);
		FMT_2_STRING(VERTEXDATA);
		FMT_2_STRING(INDEX16);
		FMT_2_STRING(INDEX32);
		FMT_2_STRING(Q16W16V16U16);
		FMT_2_STRING(MULTI2_ARGB8);
		FMT_2_STRING(R16F);
		FMT_2_STRING(G16R16F);
		FMT_2_STRING(A16B16G16R16F);
		FMT_2_STRING(R32F);
		FMT_2_STRING(G32R32F);
		FMT_2_STRING(A32B32G32R32F);
		FMT_2_STRING(CxV8U8);       

#undef FMT_2_STRING

		default:
			{
				 static const WString s_default( _S("Unknown format") );
				 return s_default;
			}
		}
	}

	// dxgi_format_to_string
	const WString& dxgi_format_to_string( DXGI_FORMAT format )
	{
		switch( format )
		{

#define	FMT_2_STRING( FMT )		case DXGI_FORMAT_##FMT##: { static const WString s_##FMT##( L#FMT ); return s_##FMT##; } break

		FMT_2_STRING(R32G32B32A32_TYPELESS);
        FMT_2_STRING(R32G32B32A32_FLOAT);
        FMT_2_STRING(R32G32B32A32_UINT);
        FMT_2_STRING(R32G32B32A32_SINT);
        FMT_2_STRING(R32G32B32_TYPELESS);
        FMT_2_STRING(R32G32B32_FLOAT);
        FMT_2_STRING(R32G32B32_UINT);
        FMT_2_STRING(R32G32B32_SINT);
        FMT_2_STRING(R16G16B16A16_TYPELESS);
        FMT_2_STRING(R16G16B16A16_FLOAT);
        FMT_2_STRING(R16G16B16A16_UNORM);
        FMT_2_STRING(R16G16B16A16_UINT);
        FMT_2_STRING(R16G16B16A16_SNORM);
        FMT_2_STRING(R16G16B16A16_SINT);
        FMT_2_STRING(R32G32_TYPELESS);
        FMT_2_STRING(R32G32_FLOAT);
        FMT_2_STRING(R32G32_UINT);
        FMT_2_STRING(R32G32_SINT);
        FMT_2_STRING(R32G8X24_TYPELESS);
        FMT_2_STRING(D32_FLOAT_S8X24_UINT);
        FMT_2_STRING(R32_FLOAT_X8X24_TYPELESS);
        FMT_2_STRING(X32_TYPELESS_G8X24_UINT);
        FMT_2_STRING(R10G10B10A2_TYPELESS);
        FMT_2_STRING(R10G10B10A2_UNORM);
        FMT_2_STRING(R10G10B10A2_UINT);
        FMT_2_STRING(R11G11B10_FLOAT);
        FMT_2_STRING(R8G8B8A8_TYPELESS);
        FMT_2_STRING(R8G8B8A8_UNORM);
        FMT_2_STRING(R8G8B8A8_UNORM_SRGB);
        FMT_2_STRING(R8G8B8A8_UINT);
        FMT_2_STRING(R8G8B8A8_SNORM);
        FMT_2_STRING(R8G8B8A8_SINT);
        FMT_2_STRING(R16G16_TYPELESS);
        FMT_2_STRING(R16G16_FLOAT);
        FMT_2_STRING(R16G16_UNORM);
        FMT_2_STRING(R16G16_UINT);
        FMT_2_STRING(R16G16_SNORM);
        FMT_2_STRING(R16G16_SINT);
        FMT_2_STRING(R32_TYPELESS);
        FMT_2_STRING(D32_FLOAT);
        FMT_2_STRING(R32_FLOAT);
        FMT_2_STRING(R32_UINT);
        FMT_2_STRING(R32_SINT);
        FMT_2_STRING(R24G8_TYPELESS);
        FMT_2_STRING(D24_UNORM_S8_UINT);
        FMT_2_STRING(R24_UNORM_X8_TYPELESS);
        FMT_2_STRING(X24_TYPELESS_G8_UINT);
        FMT_2_STRING(R8G8_TYPELESS);
        FMT_2_STRING(R8G8_UNORM);
        FMT_2_STRING(R8G8_UINT);
        FMT_2_STRING(R8G8_SNORM);
        FMT_2_STRING(R8G8_SINT);
        FMT_2_STRING(R16_TYPELESS);
        FMT_2_STRING(R16_FLOAT);
        FMT_2_STRING(D16_UNORM);
        FMT_2_STRING(R16_UNORM);
        FMT_2_STRING(R16_UINT);
        FMT_2_STRING(R16_SNORM);
        FMT_2_STRING(R16_SINT);
        FMT_2_STRING(R8_TYPELESS);
        FMT_2_STRING(R8_UNORM);
        FMT_2_STRING(R8_UINT);
        FMT_2_STRING(R8_SNORM);
        FMT_2_STRING(R8_SINT);
        FMT_2_STRING(A8_UNORM);
        FMT_2_STRING(R1_UNORM);
        FMT_2_STRING(R9G9B9E5_SHAREDEXP);
        FMT_2_STRING(R8G8_B8G8_UNORM);
        FMT_2_STRING(G8R8_G8B8_UNORM);
        FMT_2_STRING(BC1_TYPELESS);
        FMT_2_STRING(BC1_UNORM);
        FMT_2_STRING(BC1_UNORM_SRGB);
        FMT_2_STRING(BC2_TYPELESS);
        FMT_2_STRING(BC2_UNORM);
        FMT_2_STRING(BC2_UNORM_SRGB);
        FMT_2_STRING(BC3_TYPELESS);
        FMT_2_STRING(BC3_UNORM);
        FMT_2_STRING(BC3_UNORM_SRGB);
        FMT_2_STRING(BC4_TYPELESS);
        FMT_2_STRING(BC4_UNORM);
        FMT_2_STRING(BC4_SNORM);
        FMT_2_STRING(BC5_TYPELESS);
        FMT_2_STRING(BC5_UNORM);
        FMT_2_STRING(BC5_SNORM);
        FMT_2_STRING(B5G6R5_UNORM);
        FMT_2_STRING(B5G5R5A1_UNORM);
        FMT_2_STRING(B8G8R8A8_UNORM);

#undef FMT_2_STRING

		default:
			{
				 static const WString s_default( _S("Unknown format") );
				 return s_default;
			}
		}
	}

	// d3d_get_depth_bits
	DWORD d3d_get_depth_bits( D3DFORMAT fmt )
	{
		switch( fmt )
		{
		case D3DFMT_D32F_LOCKABLE:
		case D3DFMT_D32:
			return 32;

		case D3DFMT_D24X8:
		case D3DFMT_D24S8:
		case D3DFMT_D24X4S4:
		case D3DFMT_D24FS8:
			return 24;

		case D3DFMT_D16_LOCKABLE:
		case D3DFMT_D16:
			return 16;

		case D3DFMT_D15S1:
			return 15;

		default:
			return 0;
		}
	}

	// d3d_get_stencil_bits
	DWORD d3d_get_stencil_bits( D3DFORMAT fmt )
	{
		switch( fmt )
		{
		case D3DFMT_D16_LOCKABLE:
		case D3DFMT_D16:
		case D3DFMT_D32F_LOCKABLE:
		case D3DFMT_D32:
		case D3DFMT_D24X8:
			return 0;

		case D3DFMT_D15S1:
			return 1;

		case D3DFMT_D24X4S4:
			return 4;

		case D3DFMT_D24S8:
		case D3DFMT_D24FS8:
			return 8;

		default:
			return 0;
		}
	}

	// d3d_get_color_bits
	DWORD d3d_get_color_bits( D3DFORMAT fmt )
	{
		switch( fmt )
		{
		case D3DFMT_R8G8B8:
			return 8;
		case D3DFMT_A8R8G8B8:
			return 8;
		case D3DFMT_X8R8G8B8:
			return 8;
		case D3DFMT_R5G6B5:
			return 5;
		case D3DFMT_X1R5G5B5:
			return 5;
		case D3DFMT_A1R5G5B5:
			return 5;
		case D3DFMT_A4R4G4B4:
			return 4;
		case D3DFMT_R3G3B2:
			return 2;
		case D3DFMT_A8R3G3B2:
			return 2;
		case D3DFMT_X4R4G4B4:
			return 4;
		case D3DFMT_A2B10G10R10:
			return 10;
		case D3DFMT_A8B8G8R8:
			return 8;
		case D3DFMT_A2R10G10B10:
			return 10;
		case D3DFMT_A16B16G16R16:
			return 16;
		default:
			return 0;
		}
	}

	DWORD dxgi_get_color_bits( DXGI_FORMAT fmt )
	{
		switch( fmt )
		{
		case DXGI_FORMAT_R32G32B32A32_TYPELESS:
		case DXGI_FORMAT_R32G32B32A32_FLOAT:
		case DXGI_FORMAT_R32G32B32A32_UINT:
		case DXGI_FORMAT_R32G32B32A32_SINT:
		case DXGI_FORMAT_R32G32B32_TYPELESS:
		case DXGI_FORMAT_R32G32B32_FLOAT:
		case DXGI_FORMAT_R32G32B32_UINT:
		case DXGI_FORMAT_R32G32B32_SINT:
			return 32;

		case DXGI_FORMAT_R16G16B16A16_TYPELESS:
		case DXGI_FORMAT_R16G16B16A16_FLOAT:
		case DXGI_FORMAT_R16G16B16A16_UNORM:
		case DXGI_FORMAT_R16G16B16A16_UINT:
		case DXGI_FORMAT_R16G16B16A16_SNORM:
		case DXGI_FORMAT_R16G16B16A16_SINT:
			return 16;

		case DXGI_FORMAT_R10G10B10A2_TYPELESS:
		case DXGI_FORMAT_R10G10B10A2_UNORM:
		case DXGI_FORMAT_R10G10B10A2_UINT:
			return 10;

		case DXGI_FORMAT_R8G8B8A8_TYPELESS:
		case DXGI_FORMAT_R8G8B8A8_UNORM:
		case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
		case DXGI_FORMAT_R8G8B8A8_UINT:
		case DXGI_FORMAT_R8G8B8A8_SNORM:
		case DXGI_FORMAT_R8G8B8A8_SINT:
			return 8;

		case DXGI_FORMAT_B5G6R5_UNORM:
		case DXGI_FORMAT_B5G5R5A1_UNORM:
			return 5;

		default:
			return 0;
		}
	}
	// d3d_get_color_size
	DWORD d3d_get_color_size( D3DFORMAT fmt )
	{
		switch( fmt )
		{
		case D3DFMT_R8G8B8:
			return 3;
		case D3DFMT_A8R8G8B8:
			return 4;
		case D3DFMT_X8R8G8B8:
			return 4;
		case D3DFMT_R5G6B5:
			return 2;
		case D3DFMT_X1R5G5B5:
			return 2;
		case D3DFMT_A1R5G5B5:
			return 2;
		case D3DFMT_A4R4G4B4:
			return 2;
		case D3DFMT_R3G3B2:
			return 1;
		case D3DFMT_A8R3G3B2:
			return 2;
		case D3DFMT_X4R4G4B4:
			return 1;
		case D3DFMT_A2B10G10R10:
			return 4;
		case D3DFMT_A8B8G8R8:
			return 4;
		case D3DFMT_A2R10G10B10:
			return 4;
		case D3DFMT_A16B16G16R16:
			return 8;
		default:
			return 0;
		}
	}
	// dxgi_get_color_size
	DWORD dxgi_get_color_size( DXGI_FORMAT fmt )
	{
		switch( fmt )
		{
		case DXGI_FORMAT_R32G32B32A32_TYPELESS:
		case DXGI_FORMAT_R32G32B32A32_FLOAT:
		case DXGI_FORMAT_R32G32B32A32_UINT:
		case DXGI_FORMAT_R32G32B32A32_SINT:
		case DXGI_FORMAT_R32G32B32_TYPELESS:
		case DXGI_FORMAT_R32G32B32_FLOAT:
		case DXGI_FORMAT_R32G32B32_UINT:
		case DXGI_FORMAT_R32G32B32_SINT:
			return 16;

		case DXGI_FORMAT_R16G16B16A16_TYPELESS:
		case DXGI_FORMAT_R16G16B16A16_FLOAT:
		case DXGI_FORMAT_R16G16B16A16_UNORM:
		case DXGI_FORMAT_R16G16B16A16_UINT:
		case DXGI_FORMAT_R16G16B16A16_SNORM:
		case DXGI_FORMAT_R16G16B16A16_SINT:
			return 8;

		case DXGI_FORMAT_R10G10B10A2_TYPELESS:
		case DXGI_FORMAT_R10G10B10A2_UNORM:
		case DXGI_FORMAT_R10G10B10A2_UINT:
			return 4;

		case DXGI_FORMAT_R8G8B8A8_TYPELESS:
		case DXGI_FORMAT_R8G8B8A8_UNORM:
		case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
		case DXGI_FORMAT_R8G8B8A8_UINT:
		case DXGI_FORMAT_R8G8B8A8_SNORM:
		case DXGI_FORMAT_R8G8B8A8_SINT:
			return 4;

		case DXGI_FORMAT_B5G6R5_UNORM:
		case DXGI_FORMAT_B5G5R5A1_UNORM:
			return 2;

		default:
			return 0;
		}
	}

	// d3d_get_err
	const wchar_t * d3d_get_err( HRESULT result )
	{
		return DXGetErrorDescriptionW( result );
	}
	// d3d_topology_type9
	D3DPRIMITIVETYPE d3d_topology_type9( TopologyType type )
	{
		static const D3DPRIMITIVETYPE s_convert_list[TOPOLOGY_last] = {
			D3DPT_POINTLIST,
			D3DPT_LINELIST,
			D3DPT_LINESTRIP,
			D3DPT_TRIANGLELIST,
			D3DPT_TRIANGLESTRIP,
			D3DPT_TRIANGLEFAN,
			D3DPT_FORCE_DWORD,
			D3DPT_FORCE_DWORD,
			D3DPT_FORCE_DWORD,
			D3DPT_FORCE_DWORD,
		};
		return s_convert_list[type];
	}
	// d3d_topology_type10
	D3D10_PRIMITIVE_TOPOLOGY d3d_topology_type10( TopologyType type )
	{
		static const D3D10_PRIMITIVE_TOPOLOGY s_convert_list[TOPOLOGY_last] = {
			D3D10_PRIMITIVE_TOPOLOGY_POINTLIST,
			D3D10_PRIMITIVE_TOPOLOGY_LINELIST,
			D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP,
			D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
			D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP,
			D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED,
			D3D10_PRIMITIVE_TOPOLOGY_LINELIST_ADJ,
			D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ,
			D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ,
			D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ,
		};
		return s_convert_list[type];
	}
	// d3d_prim_count
	size_t d3d_prim_count( enum TopologyType type , size_t vertex_count , size_t index_count )
	{
		size_t count = 0;
		switch( type )
		{
		case TOPOLOGY_POINTS:
			if( index_count > 0 )
				count = index_count;
			else
				count = vertex_count;
			break;
		case TOPOLOGY_LINES:
			if( index_count > 0 )
				count = index_count / 2;
			else
				count = vertex_count / 2;
			break;
		case TOPOLOGY_LINESTRIP:
			if( index_count > 0 )
				count = index_count - 1;
			else
				count = vertex_count - 1;
			break;
		case TOPOLOGY_TRIANGLES:
			if( index_count > 0 )
				count = index_count / 3;
			else
				count = vertex_count / 3;
			break;
		case TOPOLOGY_TRISTRIP:
			if( index_count > 0 )
				count = index_count - 2;
			else
				count = vertex_count - 2;
			break;
		case TOPOLOGY_TRIFAN:
			if( index_count > 0 )
				count = index_count - 1;
			else
				count = vertex_count - 1;
			break;
		case TOPOLOGY_LINES_ADJ:
			if( index_count > 0 )
				count = index_count / 4;
			else
				count = vertex_count / 4;
			break;
		case TOPOLOGY_LINESTRIP_ADJ:
			if( index_count > 0 )
				count = ( index_count - 1 ) - 2;
			else
				count = ( vertex_count - 1 ) - 2;
			break;
		case TOPOLOGY_TRIANGLES_ADJ:
			if( index_count > 0 )
				count = index_count / 6;
			else
				count = vertex_count / 6;
			break;
		case TOPOLOGY_TRISTRIP_ADJ:
			if( index_count > 0 )
				count = index_count / 2 - 2;
			else
				count = vertex_count / 2 - 2;
			break;
		default:
			XS_ASSERT(false);
		}
		return count;
	}
	
} // namespace xeres
